/*
 * Copyright (C) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @addtogroup CodecBase
 * @{
 *
 * @brief CodecBase模块提供运行音视频编解码通用的结构体、字符常量、枚举。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 *
 * @since 9
 * @version 1.0
 */

/**
 * @file native_avcodec_base.h
 *
 * @brief 声明运行音视频编解码通用的结构体、字符常量、枚举。
 *
 * @since 9
 * @version 1.0
 */

#ifndef NATIVE_AVCODEC_BASE_H
#define NATIVE_AVCODEC_BASE_H

#include <stdint.h>
#include <stdio.h>
#include "native_averrors.h"
#include "native_avformat.h"
#include "native_avmemory.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct NativeWindow OHNativeWindow;
typedef struct OH_AVCodec OH_AVCodec;

/**
 * @brief 枚举OH_AVCodec的Buffer标记的类别。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @since 9
 * @version 1.0
 */
typedef enum OH_AVCodecBufferFlags {
    AVCODEC_BUFFER_FLAGS_NONE = 0,
    /** 表明该Buffer是End-of-Stream帧 */
    AVCODEC_BUFFER_FLAGS_EOS = 1 << 0,
    /** 表明该Buffer内包含关键帧 */
    AVCODEC_BUFFER_FLAGS_SYNC_FRAME = 1 << 1,
    /** 表明该Buffer内包含的数据仅仅为一帧的一部分 */
    AVCODEC_BUFFER_FLAGS_INCOMPLETE_FRAME = 1 << 2,
    /** 表明该Buffer包含Codec-Specific-Data */
    AVCODEC_BUFFER_FLAGS_CODEC_DATA = 1 << 3,
} OH_AVCodecBufferFlags;

/**
 * @brief 定义OH_AVCodec的Buffer描述信息。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @since 9
 * @version 1.0
 */
typedef struct OH_AVCodecBufferAttr {
    /** 以微秒为单位表示的该Buffer的Presentation时间戳 */
    int64_t pts;
    /** 以字节为单位表示的该Buffer内所包含数据的大小 */
    int32_t size;
    /** 有效数据在该Buffer内的起始偏移量 */
    int32_t offset;
    /** 该Buffer具有的标记，也是多个{@link OH_AVCodecBufferFlags}的组合 */
    uint32_t flags;
} OH_AVCodecBufferAttr;

/**
 * @brief 当OH_AVCodec实例运行发生错误时，该函数指针会被调用以报告具体错误信息。
 * 
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @param codec OH_AVCodec实例
 * @param errorCode 具体错误码
 * @param userData 用户特定数据
 * @since 9
 * @version 1.0
 */
typedef void (*OH_AVCodecOnError)(OH_AVCodec *codec, int32_t errorCode, void *userData);

/**
 * @brief 当输出流发生变化时，该函数指针会被调用以报告新的流描述信息。
 * 需要注意的时，OH_AVFormat指针的生命周期仅维持在该函数指针被调用时上有效，禁止在调用结束后继续访问。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @param codec OH_AVCodec实例
 * @param format 新的输出流描述信息
 * @param userData 用户特定数据
 * @since 9
 * @version 1.0
 */
typedef void (*OH_AVCodecOnStreamChanged)(OH_AVCodec *codec, OH_AVFormat *format, void *userData);

/**
 * @brief 当AVCodec运行过程中需要新的输入数据时，该函数指针会被调用，并携带一块可用的Buffer以供填入新的输入数据。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @param codec OH_AVCodec实例
 * @param index 新的可用的输入Buffer对应的索引
 * @param data 新的可用的输入Buffer
 * @param userData 用户特定数据
 * @since 9
 * @version 1.0
 */
typedef void (*OH_AVCodecOnNeedInputData)(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data, void *userData);

/**
 * @brief 当AVCodec运行过程中产生了新的输出数据时，该函数指针会被调用，并携带一块包含新输出数据的Buffer，
 * 需要注意的是，OH_AVCodecBufferAttr指针的生命周期仅维持在该函数指针被调用时有效，禁止调用结束后继续访问。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @param codec OH_AVCodec实例
 * @param index 新的输出Buffer对应的索引
 * @param data 包含新的输出数据的Buffer
 * @param attr 新的输出Buffer的描述信息，具体参考{@link OH_AVCodecBufferAttr}
 * @param userData specified data
 * @since 9
 * @version 1.0
 */
typedef void (*OH_AVCodecOnNewOutputData)(OH_AVCodec *codec, uint32_t index, OH_AVMemory *data,
    OH_AVCodecBufferAttr *attr, void *userData);

/**
 * @brief AVCodec所有的异步回调函数指针集合。注册一个该结构体实例给OH_AVCodec实例，并处理通过该回调报告
 * 的信息，以确保AVCodec正常运转。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @param onError 监听AVCodec运行错误，参考{@link OH_AVCodecOnError}
 * @param onStreamChanged 监听编解码流信息，参考{@link OH_AVCodecOnStreamChanged}
 * @param onNeedInputData 监听编解码需要输入数据，参考{@link OH_AVCodecOnNeedInputData}
 * @param onNeedInputData 监听编解码产生输出数据，参考{@link OH_AVCodecOnNewOutputData}
 * @since 9
 * @version 1.0
 */
typedef struct OH_AVCodecAsyncCallback {
    OH_AVCodecOnError onError;
    OH_AVCodecOnStreamChanged onStreamChanged;
    OH_AVCodecOnNeedInputData onNeedInputData;
    OH_AVCodecOnNewOutputData onNeedOutputData;
} OH_AVCodecAsyncCallback;

/**
 * @brief AVC视频编解码器的MIME类型。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @since 9
 * @version 1.0
 */
extern const char *OH_AVCODEC_MIMETYPE_VIDEO_AVC;

/**
 * @brief AAC音频编解码器的MIME类型。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @since 9
 * @version 1.0
 */
extern const char *OH_AVCODEC_MIMETYPE_AUDIO_AAC;

/**
 * @brief 提供统一的surface Buffer附属数据的字符描述符。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @since 9
 * @version 1.0
 */
/** surface附属数据中时间戳的字符描述符，值类型为int64 */
extern const char *OH_ED_KEY_TIME_STAMP;
/** surface附属数据中结束流的字符描述符，值类型为bool */
extern const char *OH_ED_KEY_EOS;

/**
 * @brief 为媒体播放框架提供统一的字符描述符。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @since 9
 * @version 1.0
 */
/** 轨道类型的字符描述符，值类型为uint8_t，具体见{@link OH_MediaType} */
extern const char *OH_MD_KEY_TRACK_TYPE;
/** mime类型的字符描述符，值类型为string */
extern const char *OH_MD_KEY_CODEC_MIME;
/** duration的字符描述符，值类型为int64_t */
extern const char *OH_MD_KEY_DURATION;
/** 比特率的字符描述符，值类型为uint32_t */
extern const char *OH_MD_KEY_BITRATE;
/** 最大输入尺寸的字符描述符，值类型为uint32_t */
extern const char *OH_MD_KEY_MAX_INPUT_SIZE;
/** 视频宽度的字符描述符，值类型为uint32_t */
extern const char *OH_MD_KEY_WIDTH;
/** 视频高度的字符描述符，值类型为uint32_t */
extern const char *OH_MD_KEY_HEIGHT;
/** 视频像素格式的字符描述符，值类型为int32_t，具体见{@link OH_AVPixelFormat} */
extern const char *OH_MD_KEY_PIXEL_FORMAT;
/** 音频采样格式的字符描述符，值类型为uint32_t */
extern const char *OH_MD_KEY_AUDIO_SAMPLE_FORMAT;
/** 视频帧率的字符描述符，值类型为double */
extern const char *OH_MD_KEY_FRAME_RATE;
/** 视频编码比特率模式的字符描述符，值类型为int32_t，具体见{@link OH_VideoEncodeBitrateMode} */
extern const char *OH_MD_KEY_VIDEO_ENCODE_BITRATE_MODE;
/** 音视频编码能力的字符描述符，值类型为int32_t，具体见{@link OH_AVCProfile}或{@link OH_AACProfile} */
extern const char *OH_MD_KEY_PROFILE;
/** 音频声道数的字符描述符，值类型为uint32_t */
extern const char *OH_MD_KEY_AUD_CHANNEL_COUNT;
/** 音频采样率的字符描述符，值类型为uint32_t */
extern const char *OH_MD_KEY_AUD_SAMPLE_RATE;
/** I帧间隔时长的字符描述符，值类型为int32_t，单位是毫秒 */
extern const char *OH_MD_KEY_I_FRAME_INTERVAL;
/** surface旋转角度的字符描述符，值类型为int32_t，限于{0, 90, 180, 270}，默认值为0 */
extern const char *OH_MD_KEY_ROTATION;

/**
 * @brief 媒体类型。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @since 9
 * @version 1.0
 */
typedef enum OH_MediaType {
    /** 音频轨道 */
    MEDIA_TYPE_AUD = 0,
    /** 视频轨道 */
    MEDIA_TYPE_VID = 1,
} OH_MediaType;

/**
 * @brief AVC Profile枚举。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @since 9
 * @version 1.0
 */
typedef enum OH_AVCProfile {
    AVC_PROFILE_BASELINE = 0,
    AVC_PROFILE_HIGH = 4,
    AVC_PROFILE_MAIN = 8,
} OH_AVCProfile;

/**
 * @brief AAC Profile枚举。
 * 
 * @syscap SystemCapability.Multimedia.Media.CodecBase
 * @since 9
 * @version 1.0
 */
typedef enum OH_AACProfile {
    AAC_PROFILE_LC = 0,
} OH_AACProfile;

#ifdef __cplusplus
}
#endif

#endif // NATIVE_AVCODEC_BASE_H